package mymongo

import (
	"mygo/mystruct"
	"context"
	"reflect"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

/* =================================================================================
   用户操作
*/
// 注销【退出登录】
func Logout_User(account, aestring, ipstring, UserAgent string, key []byte) string {
	if Get_Chcae_User(aestring, key) != nil {
		Logout_Chcae_User(account, aestring, ipstring, UserAgent, key)
		return "删除完成"
	}
	return "用户未登录"
}
// 登录
func Login_User(account, password, ipstring, UserAgent string, key []byte) *mystruct.Retdate {
	results := &mystruct.Retdate{"Login-User", mystruct.MyCodeOk, "succeed"}
	
	var result mystruct.Muser
	ret := MyMonDB.UserCur.FindOne(context.TODO(), bson.M{"account": account})
	if err := ret.Decode(&result); err != nil {
		results.Code = mystruct.MyCodeErr
		results.Mesg = "账号不存在"
	}
	if result.Password != password {
		results.Code = mystruct.MyCodeErr
		results.Mesg = "密码错误"
	}
	if results.Code == mystruct.MyCodeOk {
		results.Mesg = Add_Chcae_User(account, result, ipstring, UserAgent, key)
	}
	return results
}
// 注册
func Register_User(account, parent, password string, standing int64) *mystruct.Retdate {
	results := &mystruct.Retdate{"Register-User", mystruct.MyCodeErr, "账号已存在"}

	ctx := context.TODO()
	ret := MyMonDB.UserCur.FindOne(ctx, bson.M{"account": account})
	if ret.Err() == nil {
		return results
	}
	map_list := mystruct.Muser{
		Account: account,
		Password: password,
		Name: account,
		Standing: standing,
		Createuser: parent,
	}
	resid, err := MyMonDB.UserCur.InsertOne(ctx, map_list)
	if err != nil {
		results.Mesg = err.Error()
		results.Code = mystruct.MyCodeErr
	}else{
		oid, _ := resid.InsertedID.(primitive.ObjectID)
		results.Mesg = oid.Hex()
		results.Code = mystruct.MyCodeOk
	}
	return results
}
// 删除
func Delete_User(account string, user *mystruct.Muser) *mystruct.Retdate {
	results := &mystruct.Retdate{"Delete-User", mystruct.MyCodeOk, "succeed"}

	chcae_user := auth_user_edit(account, user, results)
	if results.Code != mystruct.MyCodeOk {
		return results
	}

	if user.Standing < mystruct.AUTH_Superadmin + 1 {
		_, res := MyMonDB.ApiCur.All("account", account)
		if res != nil {
			results.Code = mystruct.MyCodeErr
			results.Mesg = "用户关联的API未解绑完全"
			return results
		}
	}

	ret, err := MyMonDB.UserCur.DeleteOne(context.TODO(), bson.M{"account": account})
	results.Code = ret.DeletedCount
	if err != nil{
		results.Mesg = err.Error()
		results.Code = mystruct.MyCodeErr
	}
	if chcae_user != nil {
		Del_Chcae_User(account)
	}
	return results
}
// 修改
func Set_User(account string, data map[string]interface{}, user *mystruct.Muser) *mystruct.Retdate {
	results := &mystruct.Retdate{"Set-User", mystruct.MyCodeOk, "succeed"}

	chcae_user := auth_user_edit(account, user, results)
	if results.Code != mystruct.MyCodeOk {
		return results
	}
	bson_data := bson.D{}
	for key, val := range data {
		switch key {
			case "standing":
				standing := int64(val.(float64))
				if standing + 1 > user.Standing {
					results.Code = mystruct.MyCodeErr
					results.Mesg = "权限设置不能超过设置者本身"
					return results
				}
				if standing > mystruct.AUTH_Tourist && mystruct.AUTH_ININUSER > standing {
					bson_data = append(bson_data, bson.E{Key: key, Value: standing})
				}else{
					results.Code = mystruct.MyCodeErr
					results.Mesg = "权限设置区间为2-998"
					return results
				}
			case "edit":
				if user.Standing < mystruct.AUTH_Superadmin + 1 && chcae_user.Createuser != user.Account {
					results.Code = mystruct.MyCodeErr
					results.Mesg = "不可编辑归属选项[权限不足]"
					return results
				}
				bson_data = append(bson_data, bson.E{Key: key, Value: val.(bool)})
			case "create":
				if user.Standing < mystruct.AUTH_Superadmin + 1 && chcae_user.Createuser != user.Account {
					results.Code = mystruct.MyCodeErr
					results.Mesg = "不可编辑归属选项[权限不足]"
					return results
				}
				bson_data = append(bson_data, bson.E{Key: "createuser", Value: val.(string)})
			default:
				bson_data = append(bson_data, bson.E{Key: key, Value: val.(string)})
		}
    }

	update := bson.D{{"$set", bson_data}}
	ret, err := MyMonDB.UserCur.UpdateOne(context.TODO(), bson.M{"account": account}, update)
	if err != nil {
		results.Code = mystruct.MyCodeErr
		results.Mesg = err.Error()
		return results
	}
	results.Code = ret.ModifiedCount

	if chcae_user != nil {
		currentField := reflect.ValueOf(chcae_user).Elem()
		typeOfUser := currentField.Type()
		for key, value := range data {
			field := currentField.FieldByName(key)
			if !field.IsValid() {
	            for i := 0; i < typeOfUser.NumField(); i++ {
	               fieldType := typeOfUser.Field(i)
	               jsonTag := fieldType.Tag.Get("json")
	               if jsonTag == key {
	                  field = currentField.FieldByName(fieldType.Name)
	                  break
	               }
	            }
        	}
			if field.IsValid() && field.CanSet() {
				fieldType := field.Type()
				newValue := reflect.ValueOf(value).Convert(fieldType)
				field.Set(newValue)
			}
		}
	}
	return results
}
// 查看所有
func List_User(limit, page int64, data map[string]interface{}, user *mystruct.Muser) (*mystruct.Retdate, []mystruct.Muser) {
	results := &mystruct.Retdate{"List-User", mystruct.MyCodeOk, "succeed"}

	pipeline := []bson.M{}
	for key, val := range data {
    	if strVal, ok := val.(string); ok {
    		if strVal != "" {
    			pipeline = append(pipeline, bson.M{"$match": bson.M{key: bson.M{"$regex": primitive.Regex{Pattern: `.*` + strVal + `.*`, Options: "i"}}}})
    		}
    	}else if boolVal, ok := val.(bool); ok {
         pipeline = append(pipeline, bson.M{"$match": bson.M{key: bson.M{"$exists": boolVal}}})
    	}else if floatVal, ok := val.(float64); ok {
         pipeline = append(pipeline, bson.M{"$match": bson.M{key: bson.M{"$exists": int64(floatVal)}}})
    	}
	}
	pipeline = append(pipeline, bson.M{"$skip": page  * limit})
	pipeline = append(pipeline, bson.M{"$limit": limit})
	ctx := context.TODO()
	res_cur, err := MyMonDB.UserCur.Aggregate(ctx, pipeline)
	if err != nil {
      results.Mesg = err.Error()
      results.Code = mystruct.MyCodeErr
      return results, nil
   }
	defer res_cur.Close(ctx)

	var result []mystruct.Muser
	if err := res_cur.All(ctx, &result); err != nil {
      results.Mesg = err.Error()
      results.Code = mystruct.MyCodeErr
      return results, nil
   }
   if user.Standing < mystruct.AUTH_Superadmin + 1 {
    	for key, val := range result {
    		if user.Standing < val.Standing + 1 {
    			result[key].Password = "******"
    		}
    	}
   }
	return results, result
}